﻿#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QThread>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QMessageBox>
#include <QString>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //qDebug()<<u8"开始下载新版本安装程序";
    ui->lbTips->setWordWrap(true);
    ui->progressBar->setMaximum(100);
    ui->progressBar->setValue(0);

    connect(ui->pbOk,&QPushButton::clicked,this,&Widget::onOkClicked);
    connect(ui->pbCancel,&QPushButton::clicked,this,&Widget::onCancelClicked);


}

Widget::~Widget()
{
    delete ui;
}


void Widget::showEvent(QShowEvent *event)
{
    auto info = QString(u8"您当前的版本是:%1,即将升级到:%2,请保证网络通畅").arg(oldVersion,newVersion);
    ui->lbTips->setText(info);
}

void Widget::onOkClicked()
{
    ui->pbOk->setEnabled(false);
    ui->pbCancel->setEnabled(false);

    QNetworkAccessManager* manager = new QNetworkAccessManager(this);
    QNetworkReply* reply = manager->get(QNetworkRequest(QUrl(appUrl)));//这里就开始下载了

    connect(manager, &QNetworkAccessManager::finished, this,&Widget::onDownloadFinished);
    connect(reply, &QNetworkReply::downloadProgress,this,&Widget::onDownloading);
}

void Widget::onDownloading(qint64 bytesReceived, qint64 bytesTotal)
{
        ui->progressBar->setValue((bytesReceived * 100) / bytesTotal);
}

void Widget::onDownloadFinished(QNetworkReply *reply)
{
        if (reply->error() == QNetworkReply::NoError) {
            QByteArray data = reply->readAll();
            QFile file("winposnew.exe");
            if (file.open(QIODevice::WriteOnly)) {
                file.write(data);
                file.close();
                qDebug() << u8"文件下载成功";
                ui->lbTips->setText(u8"新版本安装文件下载成功，旧版本的小苔云即将停止运行...");
                QThread::sleep(5);
                //启动进程来安装新版本。0、暂停旧程序运行；1、卸载原程序;2、安装新程序；
                QString programName = "WinPOS.exe";
// 0、根据操作系统执行不同的命令，暂停旧程序运行
#ifdef Q_OS_WIN
                qDebug() <<  "Stopping " << programName << " on Windows...";
                QString command = QString("taskkill /IM %1").arg(programName);
                system(command.toStdString().c_str());
#elif defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
                qDebug() << "Stopping " << programName << " on Linux...";
                QString command = QString("pkill -f %1").arg(programName);
                system(command.toStdString().c_str());
#else
                qDebug() << "Unsupported operating system.";
#endif 
    //1、卸载原程序，或许程序在这里待几秒种？
                ui->lbTips->setText(u8"旧版本的小苔云即将被卸载...");

                QString uninstallPath = QCoreApplication::applicationDirPath();
                uninstallPath += "/unins000.exe";
                QFileInfo fileinfo(uninstallPath);
                //QStringList paramList;
                if(fileinfo.exists())
                {
                    QProcess uninstallProcess(this);
                    uninstallProcess.setProgram(uninstallPath);

                    connect(&uninstallProcess,&QProcess::started,this,[=](){
                        this->setWindowFlags(this->windowFlags() & ~Qt::WindowStaysOnTopHint); //退居幕后
                    });
                    connect(&uninstallProcess,QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),this,&Widget::onUninstallFinished);

                    // 启动卸载程序
                    ui->lbTips->setText(u8"旧版本的小苔云正在被卸载...");
                    uninstallProcess.start();
                    if (!uninstallProcess.waitForStarted()) {
                        auto msg = QString(u8"Failed to start program:%1").arg(programName);
                        ui->lbTips->setText(msg);
                        qDebug() << "Failed to start program:" << programName;
                        return ;
                    }

                    // 等待程序完成
                    if (!uninstallProcess.waitForFinished(300000)) {
                        qDebug() << "Program did not finish within expected time: " << programName;
                        return ;
                    }
                }

            } else {
                qDebug() << "无法打开文件";
            }
        } else {
            qDebug() << "下载失败：" << reply->errorString();
    }
        reply->deleteLater();
}

void Widget::onUninstallFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
//        auto msg = QString("exitCode is:%1,and exitStatus is %2").arg(exitCode,exitStatus);

//        QMessageBox::information(NULL,"",msg);

        ui->lbTips->setText(u8"旧版本的小苔云卸载完成...");
        if (exitStatus == QProcess::NormalExit) {
            qDebug() << "Process ended normally with code" << exitCode;
            setupNewApp();

        } else {
            qDebug() << "Process crashed with code" << exitCode;
        }
}

void Widget::setupNewApp()
{
    //2、安装新程序
    ui->lbTips->setText(u8"新版本的小苔云正在安装...");

    QProcess installProcess;
    QString installPath = QCoreApplication::applicationDirPath() + "/winposnew.exe";
    installProcess.setProgram(installPath);

    connect(&installProcess,QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),this,&Widget::onInstallFinished);

    // 启动安装程序
    //installProcess.start();
    if(installProcess.startDetached()) //独立进程启动
    {
        QThread::sleep(2);
        QCoreApplication::quit();
    }
    if (!installProcess.waitForStarted()) {
        qDebug() << "Failed to start program:" ;
        return ;
    }
    // 等待程序完成
    if (!installProcess.waitForFinished()) {
        qDebug() << "Program did not finish within expected time: " ;
        return ;
    }
}

void Widget::onInstallFinished(int exitCode,QProcess::ExitStatus exitStatus)
{
    if (exitStatus == QProcess::NormalExit)
    {
        qDebug() << "Process ended normally with code" << exitCode;

        ui->lbTips->setText(u8"新版本安装完成，我先退下了...");
        ui->pbCancel->setEnabled(true);
        QThread::sleep(2);
        QCoreApplication::quit();
    }
    else
    {
        qDebug() << "Process crashed with code" << exitCode;
    }

}

void Widget::onCancelClicked()
{
    QCoreApplication::quit();
}

